use std::sync::atomic::Ordering::Relaxed;
use std::sync::Arc;
use std::{env, fs};
use tokio::sync::Semaphore;
use tokio::task::JoinSet;

use crate::{
    caculate_px_sha1, clear_not_exists_file_info, walk_dir, FileInfos, COUNT, POOL,
    PROGRESS_PERCENT,
};

#[tauri::command]
pub async fn get_datas(path: String) -> Result<String, ()> {
    clear_not_exists_file_info().await;

    COUNT.store(0, Relaxed);

    walk_dir(&path).await;

    let mut file_infos = FileInfos::select_all_by_path(POOL.get().unwrap(), &path)
        .await
        .unwrap();

    file_infos.sort_by(|a, b| b.path.cmp(&a.path));
    file_infos.sort_by(|a, b| a.sha1.cmp(&b.sha1));

    Ok(serde_json::to_string(&file_infos).unwrap())
}

#[tauri::command]
pub async fn caculate_sha1(path: String) -> Result<String, ()> {
    let mut file_path = env::temp_dir();
    file_path.push("quchong");
    file_path.push("photos");
    file_path.push("datas.db");

    let fileinfos = FileInfos::select_all_by_path(POOL.get().unwrap(), &path)
        .await
        .unwrap();

    let semaphore = Arc::new(Semaphore::new(10));
    let mut handles = JoinSet::new();
    COUNT.store(0, Relaxed);
    let total_file = fileinfos.len();
    for i in fileinfos {
        if i.sha1.is_none() {
            let semaphore = semaphore.clone();
            handles.spawn(async move {
                let _permit = semaphore.acquire().await.unwrap();
                let image = image::open(&i.path);
                match image {
                    Ok(image) => {
                        let sha1 = Some(caculate_px_sha1(&image));
                        let colortype = Some(image.color() as u8);
                        let image1 = std::fs::File::open(&i.path).unwrap();
                        let mut bufreader1 = std::io::BufReader::new(image1);
                        let exifreader1 = exif::Reader::new();
                        let exif1 = exifreader1.read_from_container(&mut bufreader1);
                        let exif = match exif1 {
                            Ok(e) => Some(e.fields().len()),
                            Err(_) => Some(0),
                        };
                        let file_info = FileInfos {
                            id: i.id,
                            path: i.path.clone(),
                            created_time: i.created_time,
                            modified_time: i.modified_time,
                            len: i.len,
                            sha1,
                            colortype,
                            exif,
                        };
                        FileInfos::update_by_column(POOL.get().unwrap(), &file_info, "id")
                            .await
                            .unwrap();
                        COUNT.fetch_add(1, Relaxed);
                    }
                    Err(_) => {
                        COUNT.fetch_add(1, Relaxed);
                    }
                }
                *PROGRESS_PERCENT.lock().unwrap() =
                    COUNT.load(Relaxed) as f64 / total_file as f64 * 100.0;
            });
        } else {
            COUNT.fetch_add(1, Relaxed);
        }
        *PROGRESS_PERCENT.lock().unwrap() = COUNT.load(Relaxed) as f64 / total_file as f64 * 100.0;
    }

    while let Some(_) = handles.join_next().await {}

    Ok("计算完成".to_string())
}

#[tauri::command]
pub fn delete_files(vec_paths: Vec<String>) -> String {
    for i in vec_paths {
        fs::remove_file(i).unwrap_or_default();
    }
    "删除成功".to_string()
}

#[tauri::command]
pub fn get_progress_percent() -> f64 {
    *PROGRESS_PERCENT.lock().unwrap()
}

#[tauri::command]
pub fn get_walkfile_count() -> usize {
    COUNT.load(Relaxed)
}
